package com.rpc.client;

import com.rpc.protocol.RpcDecode;
import com.rpc.protocol.RpcEncode;
import com.rpc.proxy.impl.jdk.JdkInvokerInvocationHandler;
import com.rpc.transport.RequestData;
import com.rpc.transport.ResponseData;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.ToString;

import java.net.InetSocketAddress;

/**
 * @author yangzhuoleo
 * @Description ${Description}
 * @create 2017-12-31 23:39
 **/
@ToString
public class NettyClient {
    @Getter
    @Setter
    @NonNull
    private String ip;

    @Getter
    @Setter
    @NonNull
    private int port;

    private EventLoopGroup worker;

    public NettyClient(String ip, int port) {
        this.ip = ip;
        this.port = port;
        this.worker = new NioEventLoopGroup();
    }


    public static void main(String[] args) {
    }

    public void init() {
        //worker负责读写数据
        try {
            //辅助启动类
            Bootstrap bootstrap = new Bootstrap();

            //设置线程池
            bootstrap.group(worker);

            //设置socket工厂
            bootstrap.channel(NioSocketChannel.class);

            //设置管道
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) {
                    //获取管道
                    ChannelPipeline pipeline = socketChannel.pipeline();
                    //字符串解码器
                    pipeline.addLast(new RpcDecode(ResponseData.class));
                    //字符串编码器
                    pipeline.addLast(new RpcEncode(RequestData.class));
                    //处理类
                    pipeline.addLast(new ClientHandler());
                }
            });

            //发起异步连接操作
            ChannelFuture futrue = bootstrap.connect(new InetSocketAddress(ip, port)).addListener(
                    new ChannelFutureListener() {
                        @Override
                        public void operationComplete(ChannelFuture future) {
                            ConnectManager.setClientHandler(future.channel().pipeline().get(ClientHandler.class));
                        }
                    }).sync();
            //等待客户端链路关闭
            futrue.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //优雅的退出，释放NIO线程组
            worker.shutdownGracefully();
        }
    }

    public void close() {
        this.worker.shutdownGracefully();
    }

    public <T> T create(Class<T> tClass) {
        return new JdkInvokerInvocationHandler().bind(tClass);
    }


}
